/*
 * Copyright (C) 2007-2011 Borqs Ltd.
 *  All rights reserved.
 */
package com.borqs.music.util;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;

/**
 * Helper class to access to Android account manager for Borqs account
 * @author b251
 *
 */
public final class AccountUtils {
    
    public static final int ERROR_CODE_SESSION_EXPIRED = 106;
    
	//Global configuration, DO NOT MDOIFY
	public static final String BORQS_ACCOUNT_TYPE = "com.borqs";
	public static final String BORQS_ACCOUNT_PACKAGE_NAME = "com.borqs.service.accountsync";

	// key of user data in system after account login, be able to
	// access by API getUserData().
	public static final String BORQS_ACCOUNT_OPTIONS_KEY_SESSION = "borqs_session";
	public static final String BORQS_ACCOUNT_OPTIONS_KEY_NICK_NAME = "borqs_nick_name";
	public static final String BORQS_ACCOUNT_OPTIONS_KEY_UID = "borqs_uid";
	public static final String BORQS_ACCOUNT_OPTIONS_KEY_SCREEN_NAME = "borqs_screen_name";

	//Operation for the account
    private static final String OP_GET_BORQS_ID_BY_CONTACT = "op_get_borqs_id_by_contact";
//    private static final String OP_GET_USER_DATA = "op_get_user_data";
//    private static final String OP_SET_USER_DATA = "op_set_user_data";
    private static final String ARGUMENT = "arg";

    private static final String DEFAULT_AUTH_TYPE = "com.borqs.service";
    
	//Account provider URI
    private static final Uri CONTENT_ACCOUNT_URI = Uri.parse("content://"
            + "com.borqs.accountservice/account/");
	/**
     * Helper function to check if there is authenticator for
     * account type 'com.borqs'
     * @return true -   Ok for borqs account login/register by uniform ui
     *         false-   The application need to do login/register itself
     */
    public static boolean isBorqsAccountServicePreloaded(Context context){
        AuthenticatorDescription[] authenticators =
            AccountManager.get(context).getAuthenticatorTypes();
        for(AuthenticatorDescription au : authenticators){
            if(au != null && BORQS_ACCOUNT_TYPE.equals(au.type)){
                return true;
            }
        }
        return false;
    }

    /**
     * Request to add a account into system by the default login ui.
     * Require "android.permission.MANAGE_ACCOUNTS"
     * @param activity
     * @featureId the application id assigned by Borqs server
     */
    public static void requestAccountSignin(Activity activity, String featureId, AccountManagerCallback<Bundle> callback){
        //android.permission.MANAGE_ACCOUNTS
        AccountManager.get(activity).addAccount(
            BORQS_ACCOUNT_TYPE,
            null, /* authTokenType */
            new String[]{featureId}, /* requiredFeatures */
            null, /* addAccountOptions */
            activity,
            callback,
            null /* handler */);
    }

	/**
	 * Request to add a account into system by the default login ui.
	 * Require "android.permission.MANAGE_ACCOUNTS"
	 * @param activity
	 */
	public static void requestAccountSignin(Activity activity, AccountManagerCallback<Bundle> callback){
		//android.permission.MANAGE_ACCOUNTS
		AccountManager.get(activity).addAccount(
			BORQS_ACCOUNT_TYPE,
		    null, /* authTokenType */
		    null, /* requiredFeatures */
		    null, /* addAccountOptions */
		    activity,
		    callback,
		    null /* handler */);
	}

	/**
     * Request user to login the account to update session. Require
     * "android.permission.MANAGE_ACCOUNTS"
     * 
     * @param activity
     */
    public static void requestUpdateCredential(Activity activity,
            AccountManagerCallback<Bundle> callback) {
        Account account = new Account(getAccountId(activity), BORQS_ACCOUNT_TYPE);
        AccountManager.get(activity).updateCredentials(
                account, DEFAULT_AUTH_TYPE, null, activity, callback, null);
    }
    
	/**
	 * Remove the Borqs account from system.
	 * Require "android.permission.MANAGE_ACCOUNTS"
	 * @param c	-	Android context
	 */
	public static void removeAccount(Context context){
		AccountManager am = AccountManager.get(context);

		Account[] accounts = am.getAccountsByType(BORQS_ACCOUNT_TYPE);
		if(accounts.length==0){
			return;
		}
		am.removeAccount(accounts[0], null, null);
	}

	/**
	 * Retrieve the account Id/Name in the system.
	 * Require "android.permission.GET_ACCOUNTS"
	 * @param context
	 * @return borqs account id, null if no borqs account
	 */
	public static String getAccountId(Context context){
		Account[] accounts = AccountManager.get(context)
			.getAccountsByType(BORQS_ACCOUNT_TYPE);
		if(accounts.length==0){
			return null;
		}

		return accounts[0].name;
	}

	/**
	 * Common interface to retrieve the user data by key.
	 * Require "android.permission.AUTHENTICATE_ACCOUNTS"
	 * @param context
	 * @param key	-	Key of user data
	 * @return
	 */
	public static String getUserData(Context context, String key){
		if(TextUtils.isEmpty(key)){
			throw new IllegalArgumentException();
		}

		AccountManager am = AccountManager.get(context);
		Account[] accounts = am.getAccountsByType(BORQS_ACCOUNT_TYPE);
		if(accounts.length==0){
			return null;
		}
		return am.getUserData(accounts[0], key);
	}

	/**
	 * Set user data for the account.
	 * require "android.permission.AUTHENTICATE_ACCOUNTS"
	 * @param context
	 * @param key	-	Key of the user data
	 * @param value	-	value in string
	 */
	public static void setUserData(Context context, String key, String value){
		if(TextUtils.isEmpty(key)){
			throw new IllegalArgumentException();
		}

		AccountManager am = AccountManager.get(context);
		Account[] accounts = am.getAccountsByType(BORQS_ACCOUNT_TYPE);
		if(accounts.length==0){
			return;
		}
		am.setUserData(accounts[0], key, value);
	}

    /**
     * Get the Borqs-ID for a contacts
     * @param context
     * @param contactId the contact ID from Contacts provider
     * @return Borqs-ID or null if the contact is not Borqs contact
     */
    public static String getBorqsIdByContact(Context context, long contactId) {
        Uri uri = CONTENT_ACCOUNT_URI.buildUpon()
                .appendPath(OP_GET_BORQS_ID_BY_CONTACT)
                .appendQueryParameter(ARGUMENT, String.valueOf(contactId))
                .build();
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        try {
            if (cursor.moveToNext()) {
                return cursor.getString(0);
            }
        } finally {
            cursor.close();
        }
        return null;
    }
}
